home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / scheme / pcscheme / geneva / sources.exe / SOURCES / LISP / MACROS.S < prev    next >
Encoding:
Text File  |  1992-05-17  |  3.8 KB  |  111 lines

  1. ;
  2. ; Following are a few macro definitions which implement constructs in other
  3. ; LISPs. They are not intended to be fully compatible to COMMON LISP or any
  4. ; other dialect, but are included as examples of how other constructs may
  5. ; be implemented, and how Scheme itself can be extended. Note also that the
  6. ; examples lack sufficient error checking - feel free to modify, extend,
  7. ; and add to any or all of macros for your own purposes.
  8.  
  9. ;
  10. ; CATCH/THROW - A catch form evaluates some subforms in such a way that, if
  11. ; a throw is executed during such evaluation, the evaluation is aborted at 
  12. ; that point and the catch form returns a value specified by the throw. The 
  13. ; catch/throw mechanism works even if the throw form is not within the lexical 
  14. ; scope of the catch. 
  15. ;
  16. ; The tags used for this implementation of catch/throw can be either symbols, 
  17. ; strings, or numbers. Note the use of fluids and continuations in this
  18. ; implementation.
  19.  
  20. (macro catch        ;(catch tag expression)
  21.    (lambda (e)
  22.       (let ((tag  (cadr e))
  23.         (form (caddr e)))
  24.        (cond ((string? tag)
  25.           (set! tag (string->symbol tag)))
  26.          ((number? tag)
  27.           (set! tag (implode (explode tag))))
  28.          ((and (pair? tag) (eq? (car tag) 'quote))
  29.           (set! tag (cadr tag))) )
  30.  
  31.      `(call/cc (fluid-lambda (,tag) ,form)))))
  32.  
  33.  
  34. (macro throw        ;(throw tag value)
  35.    (lambda (e)
  36.       (let ((tag (cadr e))
  37.         (value (caddr e)))
  38.        (cond ((string? tag)
  39.           (set! tag (string->symbol tag)))
  40.          ((number? tag)
  41.           (set! tag (implode (explode tag))))
  42.          ((and (pair? tag) (eq? (car tag) 'quote))
  43.           (set! tag (cadr tag))) )
  44.  
  45.        `(if (and (fluid-bound? ,tag)
  46.              (continuation? (fluid ,tag)))
  47.            ((fluid ,tag) ,value)
  48.            (error "Bad tag on throw" ,tag)))))
  49.  
  50. ; PROG - The prog construct allows one to write in a statement-oriented style 
  51. ; (ala FORTRAN), using go statements that can refer to tags in the body of the 
  52. ; prog. Modern LISP programming tends to use prog infrequently, however the 
  53. ; following exercise is a good example of how Scheme may be extended to take
  54. ; on characteristics of other LISPs.
  55. ;
  56.  
  57. (macro go
  58.   (lambda (form)
  59.      (if (integer? (cadr form))
  60.         `(implode (explode ,(cadr form)))
  61.      ;else
  62.         (cdr form))))
  63.  
  64. (macro prog
  65.   (lambda (form)
  66.     (letrec 
  67.       ((tagstart '())
  68.        (buildvars
  69.      (lambda (proglist varlist)
  70.            (if (null? proglist)
  71.                varlist
  72.                ;else
  73.                (buildvars (cdr proglist)
  74.                           (if (pair? (car proglist))
  75.                               `(,(car proglist) ,@varlist)
  76.                               ;else
  77.                               `( (,(car proglist) '()) ,@varlist))))))
  78.        (buildtags
  79.      (lambda (tbodys)
  80.            (if (null? tagstart)
  81.                tbodys
  82.                ;else
  83.                (buildtags 
  84.                  `( ( ,(car tagstart) 
  85.                        (lambda () ,@(getbody (cdr tagstart) '())))
  86.                     ,@tbodys)))))
  87.        (getbody 
  88.      (lambda (exprs body)
  89.            (cond ((null? exprs)
  90.                   (set! tagstart '())
  91.                   (reverse! `((return ()) ,@body)))
  92.                  ((or (symbol? (car exprs)) (integer? (car exprs)))
  93.                   (set! tagstart
  94.                         (if (integer? (car exprs))
  95.                 `(,(implode (explode (car exprs))) ,@(cdr exprs))
  96.                             ;else
  97.                 exprs))
  98.                   (reverse! `( (,(car tagstart)) ,@body)))
  99.                  (else    
  100.            (getbody (cdr exprs) `(,(car exprs) ,@body)))))))
  101.       
  102.       (let ((letrec_body (getbody (cddr form) '()))
  103.             (letrec_vars (reverse! (buildtags (buildvars (cadr form) '())))))
  104.         
  105.         `(call/cc (lambda (return)    
  106.                 (letrec ,letrec_vars ,@letrec_body)))) )))          
  107.  
  108.